import Events from "./Events";
const Cesium = window.Cesium;
/**
 * 平台 DataSource 类
 *
 * @param {String} id 唯一标识
 * @param {simpleMap} parent simpleMap 地图实例化对象
 * @param {Object} options 选项
 * @param {String} name 平台数据名称
 */
class _BasicDataSource extends Events {
    constructor(id, parent, options) {
        super();
        this.id = id;
        this.TypeName = 'DataSource';
        this.parent = parent;
        this.simpleId = parent.simpleId;
        this._DataSource = new Cesium.CustomDataSource(id);
        this._Entities = this._DataSource.entities;
        this._Mapping = {};
        this._SenceMode = parent.SenceMode || '2D';
        this._EventStatus = {
            Click: false,
            RightClick: false,
            DBLClick: false,
            MultiClick: false,
            MultiRightClick: false,
            MultiDBLClick: false,
            Hover: false,
        }
        this._Layers = [];

        this._$Entity_Click = (event, stop) => this._Entity_Click(event, stop);
        this._$Entity_RightClick = (event, stop) => this._Entity_RightClick(event, stop);
        this._$Entity_DBLClick = (event, stop) => this._Entity_DBLClick(event, stop);

        this._$Entity_Multi_Click = (event, stop) => this._Entity_Multi_Click(event, stop);
        this._$Entity_Multi_RightClick = (event, stop) => this._Entity_Multi_RightClick(event, stop);
        this._$Entity_Multi_DBLClick = (event, stop) => this._Entity_Multi_DBLClick(event, stop);

        this._$Entity_Hover = (event, stop) => this._Entity_Hover(event, stop);


        this.StartClickEvent = options.Click || false;
        this.StartRightClickEvent = options.RightClick || false;
        this.StartDBLClickEvent = options.DBLClick || false;

        this.StartMultiClickEvent = options.MultiClick || false;
        this.StartMultiRightClickEvent = options.MultiRightClick || false;
        this.StartMultiDBLClickEvent = options.MultiDBLClick || false;

        this.StartHoverEvent = options.Hover || false;

        this._$changeSceneMode = type => this._changeSceneMode(type);
        this.parent.on('changeSceneMode', this._changeSceneMode, this);

        let viewer = this.parent.getViewer()
        viewer.dataSources.add(this._DataSource);


        this._HoverCache = [];

        // this.parent.on('Click', () => {
        //     console.log('hideMenu');
        // })
        // this.parent.on('RightClick', () => {
        //     console.log('hideMenu');
        // })
        // this.on('RightClick', (item, stop) => {
        //     stop();
        //     console.log('showMenu');
        // })

    }

    /**
     * 是否显示图层
     *
     * @memberof _BasicDataSource
     */
    set show(value) {
        this._DataSource.show = !!value;
    }
    get show() {
        return this._DataSource.show
    }

    /**
     * 鼠标左键点开启控制开关
     *
     * @memberof _BasicDataSource
     */
    set StartClickEvent(type) {
        if (!!type && !this._EventStatus.Click) {
            this._EventStatus.Click = true;
            this.parent.on('PickEntity', this._$Entity_Click, this);
        };
        if (!type && this._EventStatus.Click) {
            this._EventStatus.Click = false;
            this.parent.off('PickEntity', this._$Entity_Click);
        }
    }

    get StartClickEvent() {
        return this._EventStatus.Click
    }
    /**
     * 鼠标左键拾取多个目标点开启控制开关
     *
     * @memberof _BasicDataSource
     */
    set StartMultiClickEvent(type) {
        if (!!type && !this._EventStatus.MultiClick) {
            this._EventStatus.MultiClick = true;
            this.parent.on('PickMultiEntity', this._$Entity_Multi_Click, this);
        };
        if (!type && this._EventStatus.MultiClick) {
            this._EventStatus.MultiClick = false;
            this.parent.off('PickMultiEntity', this._$Entity_Multi_Click);
        }
    }
    get StartMultiClickEvent() {
        return this._EventStatus.MultiClick
    }

    /**
     * 鼠标右键开启控制开关
     *
     * @memberof _BasicDataSource
     */
    set StartRightClickEvent(type) {
        if (!!type && !this._EventStatus.RightClick) {
            this._EventStatus.RightClick = true;
            this.parent.on('RightPickEntity', this._$Entity_RightClick, this);
        };
        if (!type && this._EventStatus.RightClick) {
            this._EventStatus.RightClick = false;
            this.parent.off('RightPickEntity', this._$Entity_RightClick);
        }
    }

    get StartRightClickEvent() {
        return this._EventStatus.RightClick
    }
    /**
     * 鼠标右键拾取多个目标点开启控制开关
     *
     * @memberof _BasicDataSource
     */
    set StartMultiRightClickEvent(type) {
        if (!!type && !this._EventStatus.MultiRightClick) {
            this._EventStatus.MultiRightClick = true;
            this.parent.on('RightPickMultiEntity', this._$Entity_Multi_RightClick, this);
        };
        if (!type && this._EventStatus.MultiRightClick) {
            this._EventStatus.MultiRightClick = false;
            this.parent.off('RightPickMultiEntity', this._$Entity_Multi_RightClick);
        }
    }
    get StartMultiRightClickEvent() {
        return this._EventStatus.MultiClick
    }

    /**
     * 鼠标双击开启控制开关
     *
     * @memberof _BasicDataSource
     */
    set StartDBLClickEvent(type) {
        if (!!type && !this._EventStatus.DBLClick) {
            this._EventStatus.DBLClick = true;
            this.parent.on('DBLClickPickEntity', this._$Entity_DBLClick, this);
        };
        if (!type && this._EventStatus.DBLClick) {
            this._EventStatus.DBLClick = false;
            this.parent.off('DBLClickPickEntity', this._$Entity_DBLClick);
        }
    }

    get StartDBLClickEvent() {
        return this._EventStatus.DBLClick
    }

    /**
     * 鼠标双击拾取多个目标点开启控制开关
     *
     * @memberof _BasicDataSource
     */
    set StartMultiDBLClickEvent(type) {
        if (!!type && !this._EventStatus.MultiDBLClick) {
            this._EventStatus.MultiDBLClick = true;
            this.parent.on('DBLClickPickMultiEntity', this._$Entity_Multi_DBLClick, this);
        };
        if (!type && this._EventStatus.MultiDBLClick) {
            this._EventStatus.MultiDBLClick = false;
            this.parent.off('DBLClickPickMultiEntity', this._$Entity_Multi_DBLClick);
        }
    }
    get StartMultiDBLClickEvent() {
        return this._EventStatus.MultiClick
    }
    /**
     * 鼠标移入移出事件
     *
     * @memberof _BasicDataSource
     */
    set StartHoverEvent(type) {
        if (!!type && !this._EventStatus.Hover) {
            this._EventStatus.Hover = true;
            this.parent.on('MouseMove', this._$Entity_Hover, this);
        };
        if (!type && this._EventStatus.Hover) {
            this._EventStatus.Hover = false;
            this.parent.off('MouseMove', this._$Entity_Hover);
        }
    }
    get StartHoverEvent() {
        return this._EventStatus.Hover
    }

    _Entity_Hover(position, event) {
        let viewer = this.parent.getViewer()
        let pickArrayEntity = viewer.scene.drillPick(event.endPosition, null, 10, 10);
        pickArrayEntity.length && this.run('PickMultiEntity', pickArrayEntity, stop);
        var ItemArray = [];
        pickArrayEntity.forEach(item => {
            this._checkEntityType(item) && ItemArray.push(item.id._Source);
        });
        this.HoverCache = ItemArray;
    }

    set HoverCache(val) {
        if (val.length != this._HoverCache.length) {
            this._HoverCache = val;
            this.run('Hover', val);
        } else if (val.length != 0 && this._HoverCache.length != 0) {
            var isSame = true;
            var valKeyArray = [];
            var CacheArray = [];
            for (let i = 0; i < val.length; i++) {
                valKeyArray.push(val[i].id);
                CacheArray.push(this._HoverCache[i].id);
            };
            for (let i = 0; i < valKeyArray.length; i++) {
                if (!CacheArray.includes(valKeyArray[i])) {
                    isSame = false;
                    break;
                }
            };
            if (!isSame) {
                this._HoverCache = val;
                this.run('Hover', val);
            };
        }
    }
    get HoverCache() {
        return this._HoverCache
    }


    _changeSceneMode(type) {
        this._Entities.suspendEvents();
        this.run('changeSceneMode', type);
        this._Entities.resumeEvents();
    }

    _checkEntityType(event) {
        var OBJNAME = null;
        if (event.id && event.id._Source) {
            OBJNAME = event.id._Source.EntityTypeName;
        }
        if (OBJNAME == this.EntityTypeName && this._Mapping.hasOwnProperty(event.id._Source.id)) {
            return true;
        }
    }

    _Entity_Click(event, _stop) {
        if (this._checkEntityType(event)) {
            let isStop = false;
            let stop = () => isStop = true;
            event.id._Source.run && event.id._Source.run('Click', event.id._Source, stop);
            !isStop && this.run('Click', event.id._Source, _stop);
        }
    }

    _Entity_RightClick(event, _stop) {
        if (this._checkEntityType(event)) {
            let isStop = false;
            let stop = () => isStop = true;
            event.id._Source.run && event.id._Source.run('RightClick', event.id._Source, stop);
            !isStop && this.run('RightClick', event.id._Source, _stop);
        }
    }

    _Entity_DBLClick(event, _stop) {
        if (this._checkEntityType(event)) {
            let isStop = false;
            let stop = () => isStop = true;
            event.id._Source.run && event.id._Source.run('DBLClick', event.id._Source, stop);
            !isStop && this.run('DBLClick', event.id._Source, _stop);
        }
    }

    _Entity_Multi_Click(event, _stop) {
        var ItemArray = [];
        event.forEach(item => {
            this._checkEntityType(item) && ItemArray.push(item.id._Source);
        });
        ItemArray.length && this.run('MultiClick', ItemArray, _stop);
    }

    _Entity_Multi_RightClick(event, _stop) {
        var ItemArray = [];
        event.forEach(item => {
            this._checkEntityType(item) && ItemArray.push(item.id._Source);
        });
        ItemArray.length && this.run('MultiRightClick', ItemArray, _stop);
    }

    _Entity_Multi_DBLClick(event, _stop) {
        var ItemArray = [];
        event.forEach(item => {
            this._checkEntityType(item) && ItemArray.push(item.id._Source);
        });
        ItemArray.length && this.run('MultiDBLClick', ItemArray, _stop);
    }
    /**
     * 注销图层组
     *
     * @memberof _BasicDataSource
     */
    Destroy() {
        // 首先执行自定义注销事件
        this._destroy && this._destroy();

        // 注销绑定事件
        this.StartClickEvent = false;
        this.StartRightClickEvent = false;
        this.StartDBLClickEvent = false;

        this.StartMultiClickEvent = false;
        this.StartMultiRightClickEvent = false;
        this.StartMultiDBLClickEvent = false;

        this.StartHoverEvent = false;

        // 注销点击关联事件
        this.off('Click');
        this.off('RightClick');

        // 解除2D/3D切换绑定
        this.parent.off('changeSceneMode', this._changeSceneMode);
        // 删除全部元素
        this.ClearAll();
        // 删除子图层
        this._Layers.forEach(item => {
            item.Destroy();
        })
        // 删除父级图层缓存
        this.parent.removeDataSouce(this);
    }

    /**
     * 遍历数据对象方法
     *
     * @param {Function} callback 回调函数
     * @memberof _BasicDataSource
     */
    EachMapping(callback) {
        this._Entities.suspendEvents();
        for (const key in this._Mapping) {
            const element = this._Mapping[key];
            callback(element, key);
        };
        this._Entities.resumeEvents();
    }
    /**
     * 一次性添加多个对象
     *
     * @param {Array} platformArray 对象数据
     * @memberof _BasicDataSource
     * @example
     * // 注意 ：必需实现一个实例化对象的实现方法
     */
    Adds(platformArray) {
        this._Entities.suspendEvents();
        if (!this.add) {
            throw new Error("必需实现一个实例化对象的实现方法");
        }
        platformArray.forEach(item => this.add(item))
        this._Entities.resumeEvents();
    }


    /**
     * 通过ID 获取对象值
     *
     * @param {String} id 子对象唯一标识
     * @return {Entity} Entity 子对象
     * @memberof _BasicDataSource
     */
    GetMappingById(id) {
        if (this._Mapping[id]) return this._Mapping[id]
    }


    /**
     * 通过ID数组删除多个元素对象
     *
     * @param {Array} idArray 唯一标识数组
     * @memberof _BasicDataSource
     */
    RemoveMultiEntity(idArray) {
        this._Entities.suspendEvents();
        idArray.forEach(item => this.remove(item));
        this._Entities.resumeEvents();
    }

    /**
     * 通过元素 ID 删除单个对象
     *
     * @param {String} id 唯一标识
     * @memberof _BasicDataSource
     */
    Remove(id) {
        if (this._Mapping[id]) {
            this._Entities.remove(this._Mapping[id].Entity);
            this._Mapping[id].destroy && this._Mapping[id].destroy();
            delete this._Mapping[id]
        }
    }

    /**
     * 删除全部对象
     *
     * @memberof _BasicDataSource
     */
    ClearAll() {
        this.EachMapping((item, id) => this.Remove(id));
    }

    /**
     * 添加图层元素
     *
     * @param {Array} Entitys 元素集合
     * @memberof _BasicDataSource
     */
    AddEntitys(Entitys) {
        this._Entities.suspendEvents();
        Entitys.forEach(Entity => this._Entities.add(Entity))
        this._Entities.resumeEvents();
    }

    /**
     * 删除图层元素
     *
     * @param {Array} Entitys 元素集合
     * @memberof _BasicDataSource
     */
    RemoveEntitys(Entitys) {
        this._Entities.suspendEvents();
        Entitys.forEach(Entity => this._Entities.remove(Entity))
        this._Entities.resumeEvents();
    }

    /**
     * 添加图层组
     *
     * @param {DataSource} DataSource 添加子图层
     * @memberof _BasicDataSource
     */
    AddLayer(layer) {
        this._Layers.push(layer);
        // let viewer = this.parent.getViewer()
        // viewer.dataSources.add(layer._DataSource);
    }

    /**
     * 删除图层组
     *
     * @param {DataSource} DataSource 删除子图层
     * @memberof _BasicDataSource
     */
    RemoveLayer(layer) {
        for (let i = 0; i < this._Layers.length; i++) {
            const element = this._Layers[i];
            if (element == layer) {
                this._Layers.splice(i, 1);
                break;
            }
        };
    }

    /**
     * 格式化坐标点 屏幕X，Y 值转换为 经纬度坐标值
     *
     * @param {Object} Postion 屏幕XY值
     * @return {Object} 经纬度坐标对象
     * @memberof _BasicDataSource
     */
    formatPostion(Postion) {
        return this.parent.formatPostion(Postion);
    }

}




export { _BasicDataSource }